package io;

public class liLun {
    /*
        IO的基本概念
            输入与输出
                输入：
                    输入是一个从外界进入到程序的方向，通常我们需要“读取”外接的数据时，
                    使用输入。所以输入是用来读取数据的。
                输出：
                    输出是一个从程序发送到外界的方向，通常我们需要“写出”数据到外界时，
                    使用输出。所以输出是用来写出数据的。
            流的概念
                java将IO比喻为“流”，即“stream”，就像生活中的“电流”，“水流”一样，
                它是以同一个方向顺序移动的过程，只不过这里流动的是字节（2进制数据），
                所以在IO中有输入流和输出流之分，我们理解他们是连接程序与另一端的“管道”，
                用于获取或发送数据到另一端。

            InputStream与OutputStream
                java.io.InputStream：所有字节输入流的超类，其中定义了读取数据的方法，
                因此将来不管读取的是什么设备（连接该设备的流）都有这些读取的方法，
                因此我们可以用相同的方法读取不同设备中的数据
                java.io.OutputStream：所有字节输出流的超类，其中定义了写出数据的方法，

                InputStream是所有字节输入流的超类，其定义了基础的读取方法，常用的方法如下:
                    int rear()
                        读取一个字节，以int形式返回，该int值的“低八位”有效，若返回值为-1则表示EOF
                    int read(byte[] d)
                        尝试最多读取给定数组的length个字节并存入该数组，返回值为实际读取到的字节量。
                OutputStream是所有字节输出流的超类，其定义了基础的写出方法，常用的方法如下:
                    void write(int d)
                        写出一个字节，写的是给定的int的“低八位”
                    void write(byte[] d)
                        将给定的字节数组中的所有字节全部写出
     */

    /*
        文件流
            文件流的作用
                文件流是实际连接程序与硬盘中文件的“管道”，用于读写文件数据的流。
                文件流以字节为单位读写文件数据
                文件输出流：
                    可将数据从内存写入到硬盘文件中可以将数据持久保存
                文件出入流：
                    可从硬盘文件中将数据读取回到内存中是程序恢复原有状态
     */

    /*
        常用构造器
            构造器
                FileOutputStream(String filename)
                    创建一个向具有指定名称的文件中写出数据的文件输出流
                FileOutputStream(File file)
                    创建一个向指定File对象表示的文件中写出数据的文件输出流
                文件输出流创建时如果制定的文件不存在则会将该文件创建出来
                如果指定的文件所在的目录不存在会抛出异常：FileNotFoundException
                如果指定的文件已经存在并包含内容，那么文件流创建时会将原有数据全部清除
     */

    /*
        写出字节数据
            文件输出流继承自java.io.OutputStream
            文件输出流提供了超类中要求的写出字节的相关方法
                void write(int d)
                    写出一个字节。写出的是给定int值d对应2进制的“低八位”
                void write(byte[] data)
                    块写操作，一次性将给定字节数组data中所有字节写出
                void write(byte[] data,int offset,int len)
                    块写操作，一次性将给定字节数组data中从下标offset处开始连续len个字节写出
     */

    /*
        常用构造器
            构造器
                FileInputStream(String filename)
                    创建一个从具有指定名称的文件中读取数据的文件输入流
                FileInputStream(File file)
                    创建一个从指定File对象表示的文件中读取数据的文件输入流
                如果指定的文件所在的目录不存在会抛出异常：FileNotFoundException
     */

    /*
        读取字节数据
            文件输入流继承自java.io.InputStream
            文件输入流提供了超类中要求的读取字节的相关方法
                int read()
                    读取一个字节。返回的int值d表示读取的1字节数据内容，其2进制的“低八位”有效
                    如果返回值为整数-1，则表示流读取到了末位（EOF，即：End Of File）
                int read()(byte[] data)
                    块读操作，一次性读取给定字节数组data总长度的数据量并从数组第一个字节位置开始
                    存入到数组中，返回值表示实际读取到的数据量。如果返回值为-1则表示流读取到了末尾。
     */

    /*
        文件复制
            单字节读写完成的复制操作读写效率差
                主要原因是磁盘的硬件特征决定着单字节的读写性能是极其低效的
                这里涉及到磁盘很多机械特性，马达带动，电与磁的转换等问题
                越频繁的磁盘与内存间交互效率越低。
     */

    /*
        块读写
            块读操作
                超类java.io.InputStream上定义了块读字节的方法
                    public int read(byte b[]) throws IOException{...}
                从流中最多读取b.length个字节数据并存入数组b中
                返回值为实际读取到的字节数
                若返回值为-1则表示流读取到了末位。
            块写操作
                超类java.io.OutputStream上定义了块写字节的方法
                    public void write(byte b[]) throws IOException{...}
                将b数组所有字节一次性写出
     */

    /*
        块读写复制
            复制后的文件比原文件大

            块写操作
                超类java.io.OutputStream上定义了重载的块写字节的方法
                    public void write(byte b[],int off,int len) throws IOException{...}
                将b数组从下标off处开始的连续len字节一次性写出
     */

    /*
        写入文本数据
            使用字符串的getBytes()方法将字符串转换为一组字节
            使用文件输出流的块写方法write(byte[] data)

        创建FOS对象（追加模式）
            通过上一节的构造方法创建的FOS对文件进行写操作时会覆盖文件中原有数据。
            若想在文件的原有数据之后追加新数据则需要一下构造方法创建FOS
                构造方法：
                    FileOutputStream(File file,boolean append)
                    创建一个向指定File对象表示的文件中写出数据的文件输出流。
                    FileOutputStream(String filename,boolean append)
                    创建一个向具有指定名称的文件中写出数据的文件输出流。
                以上两个构造方法中，第二个参数若为true，那么通过该FOS写出的数据都是在文件末尾追加的。
     */

    /*
        读取文本数据
            使用文件输入流读取文件中的所有字节。
            使用String的构造器String(byte[] data)可以将读取的字节转换为对应的字符串。
     */

    /*
        处理流
            节点流与处理流
                节点流回顾
                    数据源明确，可以从或向一个特定的地方（节点）读或写数据。
                    真实负责搬运数据的流。
                    读写一定是建立在节点流的基础上进行的。
                什么是处理流
                    处理流：
                        是对一个已存在的流的连接和封装，通过所封装的六的功能调用实现数据读写。
                        通常处理流也称为高速流或过滤流。
                    处理流的特点：
                        不独立存在，没有意义。
                        必须对其他流进行处理，处理的既可以是节点流也可以是其他处理流。
                        使用处理流可以简化我们对读写数据的加工处理，简化读写操作。
     */

    /*
        流连接
            开发中常连接一组高级流到某个低级流上，使得读写数据以流水线式的加工处理完成这个也被称为是“流的连接”。
     */

    /*
        缓冲字节流
            在流连接中通常直接连接在低级流上
            可以保证读写字节数据的效率

            构造器
                BufferedOutputStream(OutputStream out)
                    实例化一个缓冲字节输出流并链接在指定的字节输出流上。默认缓冲区大小8kb（内部维护的byte[]
                     buf数组长度8192）
                BufferedOutputStream(OutputStream out,int size)
                    实例化一个指定缓冲区大小的缓冲字节输出流并链接在指定的字节输出流上。

            使用缓冲流连接文件流，进行文件复制。

            单字节读写效率差。

            缓冲流内部维护一个默认8192长的字节数组。
            读写会被转化为块读/写形式进行来保证效率。

            写缓冲问题
                缓冲输出流可以提高写出效率，写出数据缺乏即时性。
                当需要再执行完某写出操作后，希望将数据确实写出，而非在缓冲区中保存直到缓冲区满后才写出。
                void flush()
                    清空缓冲区，将缓冲区的数据强制写出。
                写出数据不足以装满缓冲区
                flush方法可以将已缓存的数据一次性写出
     */

    /*
        对象流
            对象序列化概念
                对象是存在于内存中的。有时候我们需要将对象保存到硬盘上，
                又或是需要将对象传输到另一台计算机上等等这样的操作。
                将对象转换为一个字节序列的过程称为对象序列化。相反则称为反序列化。
     */

    /*
        序列化
            对象输出流
                构造器
                    ObjectOutputStream(OutputStream out)
                    创建一个对象输出流并连接到指定的字节输出流上
                常用方法
                    void writeObject(Object obj)
                    将给定对象进行序列化后写出
                    -序列化的对象必须实现：java.io.Serializable接口
                    -否则会抛出异常：NotSerializableException

                对象输出流在流连接中的作用就是进行对象序列化
                将序列化后的字节通过其连接的流写出
        反序列化
            构造器
                ObjectInputStream(InputStream in)
                创建一个对象输入六并连接到指定的字节输入流上
            常用方法
                Object readObject()
                读取若干字节并进行反序列化对象将其返回
     */

    /*
        transient关键字
            对象再序列化后得到的字节序列较大，对一个对象进行序列化时可忽略不必要的属性，
            从而对序列化后得到的字节序列化“瘦身”。
            关键字transient修饰的属性再序列化时其值将被忽略。
     */

    /*
        字符流
            字符流是以字符（char）为单位读写数据的，一次处理一个unicode。
            java.io.Reader是所有字符输入流的超类。
            java.io.Writer是所有字符输出流的超类。
            字符流仅适合读写文本数据。
     */

    /*
        Reader的常用方法：
            int read()：读取一个字符，返回的int值“低16”位有效。
            int read(char[] chs)：从该留中读取 一个字符数组的length个字符并存入该数组，
            返回值为实际读取到的字符两。
        Writer的常用方法：
            void write(int c)：写出一个字符，写出给定int值“低16”位标识的字符。
            void write(char[] chs)：将给定字符数组中所有字符写出。
            void write(String str)：将给定的字符串写出。
            void write(char[] chs,int offset,int len)：将给定的字符数组中从offset处开始连续的len个字符写出。
     */
    /*
        写出字节数据
            文件输出流继承自java.io.OutputStream。
            文件输出流提供了超类中要求的写出字节的相关方法
                void write(int d)：
                写出一个字节，写出给定int值d对应二进制的“低8位”。
                void write(byte[] data)：
                块写操作，一次性将给定字节数组data中所有字节写出。
                void write(byte[] data,int offset,int len)：
                块写操作，一次性将给定字节数组data中从下标offset处开始连续的len个字节写出。
     */
    /*
        转换流
            转换流的意义
                字符流只能连接在字符流上使用。
                节点流通常都是字节流，在流连接中无法直接将字符流连接在字节流上。
                转换流在其中起到“转换器”的作用。
                    用于衔接字符流与字节流。
                    对于输出而言：其他字符流写出的数据经过转换流时会转换为字节再交给字节流写出。
                    对于输入而言：会从字节流中读取字节并转换为字符后再交给其他字符流进行读取处理。
                应用中通常不直接操作转换流。

                字符流不能直接连接在字节流上。
                而节点流通常都是字节流。
                本质原因是字符流读写字符，字节流读写字节，读写单位不同。

                转换流本身是字符流，它可以连接在字节流上。
                转换流就像转换器一样，可以衔接其他字符流与字节流。

                转换输出流可以将上层字符流写出的文本数据转换为字节再通过其连接的字节流写出。

                转换输入流可以从字节流读取相应字节并转换为字符再交给上层字符流做进一步处理。

                InputStreamReader：转换输入流
                    使用该流可以设置字符集，并按照制定的字符集从流中按照该编码将字节数据转换为字符并读取。
                OutputStreamWriter：转换输出流
                    使用该流可以设置字符集，并按照制定的字符集将字符转换为对应字节后通过该流写出。

                转换输出流构造器
                    OutputStreamWriter的构造方法：
                        OutputStreamWriter(OutputStream out,Charset cs)
                        基于给定的字节输出流以及字符编码创建转换输出流。
                        OutputStreamWriter(OutputStream out)
                        该构造方法会根据系统默认字符集创建转换输出流。

                转换输出流构造器
                    InputStreamWriter的构造方法：
                        InputStreamWriter(InputStream in,Charset cs)
                        基于给定的字节输入流以及字符编码创建转换输入流。
                        InputStreamWriter(InputStream in)
                        该构造方法会根据系统默认字符集创建转换输入流（不推荐）。
     */

    /*
        缓冲字符输出流
            PrintWriter
                PrintWriter是具有自动行刷新功能的缓冲字符输出流
                    内部总是连接BufferedWriter作为缓冲块写（默认8192长的char数组）文本数据。
                    可以按行写出字符串
                    具有自动行刷新功能

                构造器
                    提供了比较丰富的构造方法
                        PrintWriter(File file)
                        PrintWriter(String fileName)
                        PrintWriter(OutputStream out)
                        PrintWriter(OutputStream out,boolean autoFlush)
                        PrintWriter(Writer writer)
                        PrintWriter(Writer writer,boolean autoFlush)
                    其中参数为OutputStream与Writer的构造方法提供了一个可以传入boolean值的参数，
                    该参数用于表示PrintWriter是否自动刷新。

                    PrintWriter提供了丰富的重载print与println方法。
                        常用方法：
                            void print(int i)：打印整数
                            void print(char c)：打印字符
                            void print(boolean b)：打印boolean值
                            void print(char[] c)：打印字符数组
                            void print(double d)：打印double值
                            void print(float f)：打印float值
                            void print(long l)：打印long值
                            void print(String str)：打印字符串
                        上述方法都有println方法
     */
    /*
        缓冲字符出入流
            BufferedReader
                BufferedReader是缓冲字符输入流
                    内部维护一个char数组作为缓冲区（默认8192长）缓存文本数据，以快读形式保证读取效率。
                    可以按行读取字符串。

                构造器
                    BufferedReader(Reader reader)
                        创建默认8192长缓冲区的缓冲字符输入流并链接在参数指定的流上
                    BufferedReader(Reader reader,int sz)
                        创建sz指定长度缓冲区的缓冲字符输入流并连接在参数指定的流上。

                按行读取字符串
                    BufferedReader提供了一个可以便于读取一行字符串的方法：
                        String readLine()
                            该方法返回缓冲区中一行字符串，返回的字符串中不包含该换行符。
                            当返回值为null时，表示流读取到了末尾。
     */

}










